package com.translate.web.config;

import javax.annotation.Resource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.common.util.StringUtil;


@Component
@Aspect
public class ApiVisitStatistics {

	private static Logger log = LoggerFactory.getLogger(ApiVisitStatistics.class);

	// 统计请求的处理时间,每个线程是独立的
	ThreadLocal<Long> startTime = new ThreadLocal<>();
	// 整个服务是唯一的
	
	private RedisTemplate<String, Long> redisTemplate;

	/**
	 * 定义切面 - 此处代表com.example.api.client.controller包下的所有接口都会被统计
	 */
	@Pointcut("execution(* com.fingerstar.manager.controller..*.*(..))")
	public void pointCut() {

	}

	/**
	 * 在接口原有的方法执行前，将会首先执行此处的代码
	 */
	@Before("pointCut()")
	public void doBefore(JoinPoint joinPoint) throws Throwable {
		startTime.set(System.currentTimeMillis());
		new Thread(() -> {
			// 获取传入目标方法的参数
			Class<?> type = joinPoint.getSignature().getDeclaringType();
			String className = type.getName();
			String methodName = joinPoint.getSignature().getName();
			String key = className + "-" + methodName;
			
			key = StringUtil.compress(key);
			
			// 计数：如果不存在key，就设置为0，如果存在就在基础上加1
			HashOperations<String, String, Long> hashOperations = redisTemplate.opsForHash();
			
			String redisKey = "apiVisitStatistics";
			
			Long apiStatistics = hashOperations.get(redisKey, key);
			
			if (null != apiStatistics) {
				Long value =  apiStatistics + 1 ;
				
				hashOperations.put(redisKey, key, value);
			} else {
				hashOperations.put(redisKey, key, 1L);
			}
			
			// 接收到请求，记录请求内容
//			ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//			HttpServletRequest request = attributes.getRequest();
//			// 记录请求的内容
////	        log.info("Aspect_URL:" + request.getRequestURL().toString());
	//
//			log.info("Aspect_Method:" + request.getMethod());
			log.info("Api访问次数：" + key + "=" + hashOperations.get(redisKey, key));
		}).start();
	}

	/**
	 * 只有正常返回才会执行此方法 记录接口访问时长
	 */
	@AfterReturning(returning = "returnVal", pointcut = "pointCut()")
	public void doAfterReturning(JoinPoint joinPoint, Object returnVal) {
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		log.info("方法执行时间:" + (System.currentTimeMillis() - startTime.get()));

	}

	/**
	 * 当接口报错时执行此方法
	 */
	@AfterThrowing(pointcut = "pointCut()")
	public void doAfterThrowing(JoinPoint joinPoint) {
//		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
//				.getRequest();
		log.info("接口访问失败，URI:[{}], 耗费时间:[{}] ms", joinPoint.getTarget(),
				System.currentTimeMillis() - startTime.get());
	}

	@Resource
	public void setRedisTemplate(RedisTemplate<String, Long> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
}